package pl.puntin.punclient.controller;

import java.awt.image.BufferedImage;
import java.io.IOException;
import java.lang.reflect.Type;
import java.net.ConnectException;
import java.net.NoRouteToHostException;
import java.net.SocketTimeoutException;
import java.net.UnknownHostException;
import java.util.HashMap;
import java.util.Map;
import java.util.Timer;
import java.util.TimerTask;

import pl.puntin.punclient.messages.AddRoomFalseMessage;
import pl.puntin.punclient.messages.AddRoomOkMessage;
import pl.puntin.punclient.messages.ChatMessage;
import pl.puntin.punclient.messages.CheckConnectionMessage;
import pl.puntin.punclient.messages.ConnectionLostMessage;
import pl.puntin.punclient.messages.ConnectionOkMessage;
import pl.puntin.punclient.messages.CreateRoomMessage;
import pl.puntin.punclient.messages.EndOfGameMessage;
import pl.puntin.punclient.messages.GameAlreadyBeginedMessage;
import pl.puntin.punclient.messages.GiveUpMessage;
import pl.puntin.punclient.messages.ImageMessage;
import pl.puntin.punclient.messages.JoinRoomMessage;
import pl.puntin.punclient.messages.JoinRoomOkMessage;
import pl.puntin.punclient.messages.LeaveRoomMessage;
import pl.puntin.punclient.messages.ListenerThreadIsDying;
import pl.puntin.punclient.messages.LoginFalseMessage;
import pl.puntin.punclient.messages.LoginMessage;
import pl.puntin.punclient.messages.LoginOkMessage;
import pl.puntin.punclient.messages.LogoutMessage;
import pl.puntin.punclient.messages.Message;
import pl.puntin.punclient.messages.NewRoundMessage;
import pl.puntin.punclient.messages.NotJoinRoomMessage;
import pl.puntin.punclient.messages.NotStartNewGameMessage;
import pl.puntin.punclient.messages.PunForDrawerMessage;
import pl.puntin.punclient.messages.RoomListMessage;
import pl.puntin.punclient.messages.RoomListPleaseMessage;
import pl.puntin.punclient.messages.SenderThreadIsDying;
import pl.puntin.punclient.messages.StartNewGameMessage;
import pl.puntin.punclient.messages.StartNewGameOkMessage;
import pl.puntin.punclient.messages.UnknowMessage;
import pl.puntin.punclient.messages.UpdateRankingMessage;
import pl.puntin.punclient.networkadapter.NetworkAdapter;
import pl.puntin.punclient.view.View;

/** 
 *	Klasa zarzadza komunikacja miedzy klientem 
 *  a serwerem, porzez obsluge przychdzacych
 *  wiadomosci(wiadomosci ktore sa w kolejce
 *  blokujacej, nie te ktore bezposrednio pochadza
 *  z sieci), a takze przez obsluge wydarzen
 *  pochdzacych z widoku.
 *  
 *  @author kakus
 */
public class Controller
{

	private static final long CHECK_CONNECTION_PEROID = 5000;

	private static final long CHECK_CONNECTION_DELAY = 5000;

	/**
	 * Obiekt zajmujacy sie obsluga sieci 
	 */
	private NetworkAdapter networkAdapter;
	
	/**
	 * Mapuje wiadomosci na odpowiednie obiekty ktore potrafia
	 * obsluzyc dana wiadomosc.
	 */
	private final Map<Type, MessageHandler> messageHandlerMap;
	
	public enum ApplicationState
	{
		/*
		 *		1 aplikacja startuje
		 *		 <- C_LOGIN
		 *		2 oczekiwanie na polaczenie 
		 *		-> S_LOGIN_OK
		 *		3 oczekiwanie na liste pokoji
		 *		-> S_ROOM_LIST
		 *		4 oczekiwanie na wybor pokoju lub stworzenie nowego
		 *		-> S_JOIN_ROOM_OK || S_ADD_ROOM_OK
		 *		5 w pokoju gry, oczekując na rozgrywke
		 *		-> S_START_NEW_GAME_OK
		 *		
		 */
		JUST_STARTED,
		TRYING_TO_CONNECT,
		WAITING_FOR_ROOM_LIST,
		JOINING_GAME,
		IN_GAME,
		PLAYING_GAME
		
	}
	
	/**
	 * Stan w jakim znajduje sie aplikacja 
	 */
	ApplicationState applicationState = ApplicationState.JUST_STARTED;

	/**
	 *	Widok aplikacji 
	 */
	private final View view;
	
	/**
	 * Watek kontrollera
	 */
	private Thread mainThread;

	/**
	 * Dzieki temu timerowi, sprawdzane jest polaczenie
	 */
	private final Timer checkConnectionTimer;

	/**
	 * 
	 */
	protected boolean connectioIsOkey = true;
	
	public Controller()
	{
		checkConnectionTimer = new Timer();
		messageHandlerMap = new HashMap<Type, MessageHandler>();
		
		/*
		 * Ponizej sa rejestrowane klasy(no w prawdzie to obiekty)
		 * ktore obsluguja dane wiadomosci.
		 */

		/*
		 * Wiadmosci pochodzace z klienta
		 */
		messageHandlerMap.put(UnknowMessage.class, new UnknowMessageHandler());
		messageHandlerMap.put(ConnectionLostMessage.class, new ConnectionLostHandler());
		messageHandlerMap.put(SenderThreadIsDying.class, new SenderThreadIsDyingHandler());
		messageHandlerMap.put(ListenerThreadIsDying.class, new ListenerThreadIsDyingHandler());
		
		/*
		 * Wiadmosci unisex
		 */
		messageHandlerMap.put(ChatMessage.class, new ChatMessageHandler());
		messageHandlerMap.put(ImageMessage.class, new ImageMessageHandler());
		messageHandlerMap.put(CheckConnectionMessage.class, new CheckConnectionHandler());
		messageHandlerMap.put(ConnectionOkMessage.class, new ConnectionOkHandler());
		
		messageHandlerMap.put(LoginOkMessage.class, new LoginOkHandler());
		messageHandlerMap.put(RoomListMessage.class, new RoomListHandler());
		messageHandlerMap.put(LoginFalseMessage.class, new LoginFalseHandler());
		messageHandlerMap.put(AddRoomOkMessage.class, new AddRoomOkHandler());
		messageHandlerMap.put(AddRoomFalseMessage.class, new AddRoomFalseHandler());
		messageHandlerMap.put(NotJoinRoomMessage.class, new NotJoinRoomHandler());
		messageHandlerMap.put(JoinRoomOkMessage.class, new JoinRoomOkHandler());
		messageHandlerMap.put(NotStartNewGameMessage.class, new StartNewFalseMessageHandler());
		messageHandlerMap.put(PunForDrawerMessage.class, new PunMessageHandler());
		messageHandlerMap.put(StartNewGameOkMessage.class, new StartNewGameOkHandler());
		
		//TODO nie ma end of round obslugi
/*		messageHandlerMap.put(DrawerPassesMassege.class, new DrawerPassesHandler());
		messageHandlerMap.put(SomeOneGuessedMessage.class, new SomeOneGuessedHandler());
		messageHandlerMap.put(DawerLeaveMessage.class, new DawerLeaveHandler());
		messageHandlerMap.put(RoundTimeoutMessage.class, new RoundTimeoutHandler());
		messageHandlerMap.put(YouAreWinnerMessage.class, new YouAreWinnerHandler());
*/
		messageHandlerMap.put(NewRoundMessage.class , new NewRoundHandler());
		messageHandlerMap.put(EndOfGameMessage.class, new EndOfGameHandler());
		messageHandlerMap.put(UpdateRankingMessage.class, new UpdateRankingHandler());
		messageHandlerMap.put(GameAlreadyBeginedMessage.class, new GameBeginedHandler());
		/*		messageHandlerMap.put(PlayerLogoutMessage.class, new PlayerLogoutHandler());
		messageHandlerMap.put(ForeverAloneMessage.class, new ForeverAloneHandler());
		messageHandlerMap.put(NewPlayerLoginMessage.class, new NewPlayerLoginHandler());
*/		view = new View(this);
	}
	
	/**
	 * Glowna petla programu. Odbierz wiadomosci z kolejki
	 * i wywolaj odpowiednia funkcje obslugujaca dana wiadomosc.
	 */
	public void start()
	{
		
		mainThread = new Thread(new Runnable()
		{
			
			@Override
			public void run()
			{
				while( true )
				{
					try
					{
						Message message = networkAdapter.receive();				
						messageHandlerMap.get(message.getClass()).handleMessage(message);
					}
					catch (InterruptedException e)
					{
						view.errorMessage("Glowny watek konczy sie");
						break;
					}
					catch (NullPointerException e) {
						view.errorMessage("NetworkAdapter jest nie stworzony, lub wiadomosc nie jest obslugiwana. Wychodze");
						e.printStackTrace();
						break;
					}
				}				
			}
		});
	}
	
	
	/**
	 * Probuje sie zalgowac do serwera
	 * @param host
	 * @param port
	 * @param login
	 */
	public void loginToServer(final String host, final int port, final String login)
	{
		view.lockLoginView();
		
		new Thread(new Runnable()
		{
			
			@Override
			public void run()
			{
				switch(applicationState)
				{
				case JUST_STARTED:
					try
					{
						view.tryingToConnect();
						networkAdapter = new NetworkAdapter(host, port);
						networkAdapter.startListen();
						networkAdapter.startSending();
						view.logMessage("Udalo sie podlaczyc do serwera");
						startCheckingConnection();
						
						/*
						 * Uruchom petle obslugi wiadmosci
						 */
						mainThread.start();
						networkAdapter.send(new LoginMessage(login));
						view.logMessage("Wyslalem login do serwera, czekam na odpowiedz ...");
						applicationState = ApplicationState.TRYING_TO_CONNECT;
					}
					catch (NoRouteToHostException e)
					{
						view.errorMessage("Nie mozna odnalesc hosta: "+e.getMessage());
						view.popErrorMessage(e.getMessage());
						view.reLogin();
					}
					catch (SocketTimeoutException e)
					{
						view.errorMessage("Blad podczas proby polaczenia, przekroczone czas oczekiwania");
						view.popErrorMessage(e.getMessage());
						view.reLogin();
					}
					catch (ConnectException e)
					{
						view.errorMessage("Blad podczas proby polaczenia: "+e.getMessage());
						view.popErrorMessage(e.getMessage());
						view.reLogin();
					}
					catch (UnknownHostException e)
					{
						view.errorMessage("Nieznany host: "+e.getMessage());
						view.popErrorMessage(e.getMessage());
						e.printStackTrace();
					}
					catch (IOException e)
					{
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
					catch (InterruptedException e)
					{
						// TODO blad podczas odkladania wiadmosci do wyslania
						e.printStackTrace();
					}
					break;
				case TRYING_TO_CONNECT:
					try {
						networkAdapter.send(new LoginMessage(login));
						view.logMessage("Wyslalem login do serwera jeszcze raz, czekam na odpowiedz ...");
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
					break;
				default:
					
					//TODO po wylogowaniu sie nie da sie juz zalogowac
					view.errorMessage("Blad. (LoginToServer)");
					break;
				}
				
			}

		}).start();
	}
	
	private void startCheckingConnection()
	{
		checkConnectionTimer.schedule(new TimerTask()
		{
			
			@Override
			public void run()
			{
				if(connectioIsOkey)
				{
					try
					{
						connectioIsOkey = false;
						view.logMessage("SEND: CHECK_CONN");
						networkAdapter.send(new CheckConnectionMessage());
					}
					catch (InterruptedException e)
					{
						e.printStackTrace();
					}
				}
				else
				{
					view.popErrorMessage("Serwer nie odpowiada ...");
					view.errorMessage("Serwer nie odpowiada ...");
					checkConnectionTimer.cancel();
					terminateApplication();
				}
				
			}
		}, CHECK_CONNECTION_DELAY, CHECK_CONNECTION_PEROID);
		
	}
	
	public void setLogin(final String login)
	{
		view.login = login;
	}
	
	/*public void sendLogin(final String login)
	{
		try {
			networkAdapter.send(new LoginMessage(login));
		} catch (InterruptedException e) {
			view.errorMessage("Nie udalo sie wyslac loginu do servera.(sendLogin)");
			e.printStackTrace();
		}
	}*/
	
	public void creatRoom()
	{
		try {
			view.logMessage("Tworze nowy pokoj");
			networkAdapter.send(new CreateRoomMessage());
		} catch (InterruptedException e) {
			view.errorMessage("Nie mozesz stworzyc pokoju, sprobuj jeszcze raz. (createRoom)");
			e.printStackTrace();
		}
	}
	
	public void popMessage(final String s)
	{
		view.popUpMessage(s);
	}
	
	public void sendChatMessage(final String message)
	{
		try {
			view.logMessage("Wysylam wiadomosc: "+message);
			networkAdapter.send(new ChatMessage(message));
		} catch (InterruptedException e) {
			view.errorMessage("Nie udało sie wysłać wiadomości. (sendChatMessage)");
			e.printStackTrace();
		}
	}
	
	public void joinRoom(final String roomId)
	{
		try {
			view.logMessage("Probuje sie dolaczyc do pokoju "+roomId);
			networkAdapter.send(new JoinRoomMessage(Byte.parseByte(roomId)));
		} catch (InterruptedException e) {
			view.errorMessage("Nie udało sie dołączyćdo pokoju. (joinRoom)");
			e.printStackTrace();
		}
	}
	
	/**
	 * Prosi o listę pokoii
	 */
	public void getRoomList()
	{
		try {
			view.logMessage("Prosze o liste pokoji");
			networkAdapter.send(new RoomListPleaseMessage());
		} catch (InterruptedException e) {
			view.errorMessage("Nie udało się wysłąć prośby o pokoje. (getRoomList)");
			e.printStackTrace();
		}
	}
	
	/**
	 * Wysyła pośbę o rozpoczęcie gry
	 */
	public void gameStart() 
	{
		try {
			view.logMessage("Rozpoczynam nowa gre");
			networkAdapter.send(new StartNewGameMessage());
		} catch (InterruptedException e) {
			view.errorMessage("Nie udało rozpocząć gry. (gameStart)");
			e.printStackTrace();
		}
	}

	/**
	 * Opusc gre
	 */
	public void leaveGame() {
		try {
			view.logMessage("Opuszczam gre");
			networkAdapter.send(new LeaveRoomMessage());
			getRoomList();
		} catch (InterruptedException e) {
			view.errorMessage("Nie udało się wysłać wiadomości opuszczeniu gry. (leaveGame)");
			e.printStackTrace();
		}		
	}
	
	public void sendImage(final BufferedImage bufferedImage)
	{
		if(networkAdapter == null)
		{
			return;
		}
		
		try
		{
			view.logMessage("Wysylam obrazek");
			networkAdapter.send(new ImageMessage(bufferedImage));
		}
		catch (InterruptedException e)
		{
			view.errorMessage("Nie udało sie wysłać obrazka. (sendImage)");
			e.printStackTrace();
		}
	}

	/**
	 * Inteface do obslugi wiadomosci. Poniewaz w javie nie ma
	 * wskaznikow na funkcje trzeba tworzyc obiekty i na rozne
	 * sposoby implementowac funkcje handleMessage
	 * 
	 * @author kakus
	 *
	 */
	private interface MessageHandler
	{
		public void handleMessage(final Message message);
	}
	
	/**
	 * Serwer mowi ze polaczenie jest okey :)
	 * @author kakus
	 *
	 */
	class LoginOkHandler implements MessageHandler
	{
		
		@Override
		public void handleMessage(final Message message)
		{
			
			switch (applicationState)
			{
			case TRYING_TO_CONNECT:
				try
				{
					view.logMessage("Login okej");
					networkAdapter.send(new RoomListPleaseMessage());
					applicationState = ApplicationState.WAITING_FOR_ROOM_LIST;
				}
				catch (InterruptedException e)
				{
					view.errorMessage("Watek upadl jak troja i nei wyslal prosby o liste pokoii");
					e.printStackTrace();
				}
				break;
				
			default:
				view.errorMessage("Got message LOGIN_OK, but application wasn't waiting for it.");
				break;
			}
		}
		
	}

	public class AddRoomFalseHandler implements MessageHandler {
		

		@Override
		public void handleMessage(final Message message) {
			
			switch (applicationState)
			{
			case JOINING_GAME:
				view.popErrorMessage("Nie udało się utworzyć pokoju!");	
				break;
			default:
				view.errorMessage("You can't add room while You are not able to room.");
				break;
			}
			
		}
	}
	
	/**
	 * Klasa obslugujaca wiadomosc tekstowa.
	 * 
	 * @author kakus
	 *
	 */
	class ChatMessageHandler implements MessageHandler
	{
		@Override
		public void handleMessage(final Message message)
		{
			switch (applicationState)
			{
			case PLAYING_GAME:
				ChatMessage chatMessage1 = (ChatMessage)message;
				view.chatMessage(chatMessage1.text);
				view.logMessage("Chat "+chatMessage1.text);
				break;
			case IN_GAME:
				ChatMessage chatMessage = (ChatMessage)message;
				view.chatMessage(chatMessage.text);
				view.logMessage("Chat "+chatMessage.text);
				break;
			default:
				view.errorMessage("You are getting Chat message, but you can't handle it.");
				break;
			}
		}
	}
	
	public class StartNewFalseMessageHandler implements MessageHandler {
		
		@Override
		public void handleMessage(final Message message) {
			switch (applicationState)
			{
			case IN_GAME:
				view.popErrorMessage("Nie możesz rozpocząć gry, jest zbyt mało graczy.");
				break;
			case PLAYING_GAME:
				view.errorMessage("You can't start game, but you already started.");
				break;
			default:
				view.errorMessage("You are getting signal to start a game, but you can't do it.");
				break;
			}

			
		}	
	}
	
	public class JoinRoomOkHandler implements MessageHandler {
		
		@Override
		public void handleMessage(final Message message) {
			switch (applicationState)
			{
			case JOINING_GAME:
				JoinRoomOkMessage joinMessage = (JoinRoomOkMessage) message;
				view.logMessage("Dolaczylem sie do pokoju: "+joinMessage.idRoom);
				view.joinExistingGame(joinMessage.idRoom);
				applicationState = ApplicationState.IN_GAME;
				break;
			default:
				view.errorMessage("You are getting signal to joinRoom, but you can't. ");
				break;
			}
		}
		
	}
	
	public class NotJoinRoomHandler implements MessageHandler {
		
		@Override
		public void handleMessage(final Message message) {
			switch (applicationState)
			{
			case JOINING_GAME:
				view.popErrorMessage("Nie udało się dołączyć do pokoju. Spróbuj jeszcze raz.");
				break;
			default:
				view.errorMessage("You are getting notJoinRoomMessage, but you even couldn't handle it, pathetic. ");
				break;
			}
		}
		
	}

	class AddRoomOkHandler implements MessageHandler
	{
		@Override
		public void handleMessage(final Message message)
		{
			switch (applicationState)
			{
			case JOINING_GAME:
				AddRoomOkMessage roomMessage = (AddRoomOkMessage)message;
				view.logMessage("Stworzylem i dolaczylem od pokoju: "+roomMessage.text);
				view.joinExistingGame(roomMessage.text);
				applicationState = ApplicationState.IN_GAME;
				break;
			default:
				view.errorMessage("You are getting signal to createRoom, but you can't handle it. ");
				break;
			}
		}
	}
	/**
	 * Obsluguje wiadomosci o nieznany typie
	 * @author kakus
	 *
	 */
	class UnknowMessageHandler implements MessageHandler
	{

		@Override
		public void handleMessage(final Message message)
		{
			UnknowMessage unknowMessage = (UnknowMessage)message;
			view.errorMessage("Nie znany typ wiadmosci: "+unknowMessage.messageCode);
		}
		
	}
	/**
	 * Obs�uguje wiadomosc o sukcesie w stworzeniu pokoju
	 * @author luk
	 *
	 */
	class RoomListHandler implements MessageHandler
	{

		@Override
		public void handleMessage(final Message message)
		{
			switch (applicationState)
			{
			case WAITING_FOR_ROOM_LIST:
				view.logMessage("Dostalem liste pokoji");
				view.youAreNotInRoomView();
				view.displayRoomList((RoomListMessage) message);
				applicationState = ApplicationState.JOINING_GAME;
				break;
			case JOINING_GAME:
				view.logMessage("Dostalem liste pokoji");
				view.displayRoomList((RoomListMessage) message);
				break;
			case IN_GAME:
				view.logMessage("Dostalem liste pokoji");
				view.youAreNotInRoomView();
				view.displayRoomList((RoomListMessage) message);
				applicationState = ApplicationState.JOINING_GAME;
				break;
			case PLAYING_GAME:
				view.logMessage("Dostalem liste pokoji");
				view.youAreNotInRoomView();
				view.displayRoomList((RoomListMessage) message);
				applicationState = ApplicationState.JOINING_GAME;
				break;
			default:
				view.errorMessage("You are getting roomList, but you can't handle it. ");
				break;
			}

		}
		
	}
	
	/**
	 * Utrata polaczenia
	 * @author kakus
	 *
	 */
	class ConnectionLostHandler implements MessageHandler
	{
		
		@Override
		public void handleMessage(final Message message)
		{
			view.errorMessage("Connection lost");
			view.popErrorMessage("Connection lost");
			terminateApplication();
		}
		
	}
	
	class StartNewGameOkHandler implements MessageHandler {
		
		@Override
		public void handleMessage(final Message message)
		{
			switch (applicationState)
			{
			case IN_GAME:
				view.logMessage("Serwer pozwala na rozpoczecie gry");
				view.beginGame();
				applicationState = ApplicationState.PLAYING_GAME;
				break;
			default:
				view.errorMessage("You are can start new game, but you can't handle it. ");
				break;
			}
		}	
	}
	
	class ImageMessageHandler implements MessageHandler
	{

		@Override
		public void handleMessage(final Message message)
		{
			switch (applicationState)
			{
			case PLAYING_GAME:
				if(view.getDrawer() == false)
				{
					view.logMessage("Odebralem obrazek");
					view.displayImageMessage((ImageMessage)message);
					break;
				}
			default:
				view.errorMessage("You get image, but you can't handle it. ");
				break;
			}
		}
		
	}
	
	class PunMessageHandler implements MessageHandler
	{
		
		@Override
		public void handleMessage(final Message message)
		{
			switch (applicationState)
			{
			case PLAYING_GAME:
				view.youAreDrawerr();
				PunForDrawerMessage punMessage = (PunForDrawerMessage) message;
				view.logMessage("Bedziesz rysowal, haslo: "+punMessage.punnie);
				view.youAreDrawer(punMessage.punnie);
				break;
			default:
				view.errorMessage("It's impossible, to draw while you are not playing game! ");
				break;
			}
		}
		
	}
	
	class LoginFalseHandler implements MessageHandler
	{
		@Override
		public void handleMessage(final Message message) {
			switch (applicationState)
			{
			case TRYING_TO_CONNECT:
				view.popErrorMessage("Login zajęty");
				view.errorMessage("Login zajety");
				view.reLogin();
				break;	
			default:
				view.errorMessage("You are getting loginFalseMessage. But you surly got good login already. ");
				break;
			}
		}
		
	}
	
	

/*	
	public class DrawerPassesHandler implements MessageHandler {
		
		@Override
		public void handleMessage(Message message) {
			view.beginNextRoundDrawerPass();
		}	
	}
	
	public class SomeOneGuessedHandler implements MessageHandler {
		
		@Override
		public void handleMessage(Message message) {
			SomeOneGuessedMessage tmp = (SomeOneGuessedMessage) message;
			view.beginNextRoundSomebodyWinned(tmp.NameOfWinner);
		}
		
	}
	public class DawerLeaveHandler implements MessageHandler {
	
		@Override
		public void handleMessage(Message message) {
			view.drawerLeftTheGame();
		}
		
	}
	public class RoundTimeoutHandler implements MessageHandler {
		
		@Override
		public void handleMessage(Message message) {
			view.tiomeOut();
		}
		
	}
	public class EndOfGameHandler implements MessageHandler {
		
		@Override
		public void handleMessage(Message message) {
			
			
		}
		
	}*/

	
	public class NewRoundHandler implements MessageHandler {
		
		
		@Override
		public void handleMessage(final Message message) {
			switch (applicationState)
			{
			case PLAYING_GAME:
				view.youAreNotDrawer();
				view.newRound();
				break;
			default:
				view.errorMessage("You can't start new round while you are not in game. ");
				break;
			}
		}
		
	}
	
	public class EndOfGameHandler implements MessageHandler {
		
		@Override
		public void handleMessage(final Message message) {
			
			switch (applicationState)
			{
			case PLAYING_GAME:
				view.endOfGame();
				applicationState = ApplicationState.IN_GAME;
				break;
			default:
				view.errorMessage("You can't end game if you even was not playing. ");
				break;
			}
		}
		
	}

	public class UpdateRankingHandler implements MessageHandler {

		@Override
		public void handleMessage(final Message message) {
			switch (applicationState)
			{
			case PLAYING_GAME:
				view.logMessage("Otrzymalem ranking");
				UpdateRankingMessage um = (UpdateRankingMessage) message;
				view.updateRanking(um.names, um.points);
				break;
			case IN_GAME:
				view.logMessage("Otrzymalem ranking");
				UpdateRankingMessage um1 = (UpdateRankingMessage) message;
				view.updateRanking(um1.names, um1.points);
				break;
			default:
				view.errorMessage("You can't update ranking if you are not in gameView. ");
				break;
			}
		}

	}

	public class SenderThreadIsDyingHandler implements MessageHandler {
		
		@Override
		public void handleMessage(final Message message)
		{
			view.errorMessage("Watek wysylania umarl :(");
		}
		
	}
	
	public class ListenerThreadIsDyingHandler implements MessageHandler {
		
		@Override
		public void handleMessage(final Message message)
		{
			view.errorMessage("Watek odbierania umarl :(");
		}
		
	}
	
	public void logout()
	{
		view.logMessage("Logout");
		try
		{
			networkAdapter.send(new LogoutMessage());
			applicationState = ApplicationState.JUST_STARTED;
		}
		catch (InterruptedException e)
		{
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		terminateApplication();
	}

	public void terminateApplication()
	{
//		networkAdapter.disconnect();
//		mainThread.interrupt();
//		networkAdapter = null;
//		applicationState = ApplicationState.JUST_STARTED;
//		view.reLogin();
		networkAdapter.disconnect();
		System.exit(1);
	}
	
	public class GameBeginedHandler implements MessageHandler {

		@Override
		public void handleMessage(final Message message) {
			switch (applicationState)
			{
			case IN_GAME:
				view.youAreNotDrawer();
				view.gameAlreadyBegined();
				applicationState = ApplicationState.PLAYING_GAME;
				break;
			case PLAYING_GAME:
				break;
			default:
				view.errorMessage("You play game while you are not in room.");
				break;
			}
		}

	}

	public class ConnectionOkHandler implements MessageHandler {
		
		@Override
		public void handleMessage(final Message message)
		{
			view.logMessage("RECV: CONNECTION_OK");
			connectioIsOkey = true;
			
		}
		
	}
	
	public class CheckConnectionHandler implements MessageHandler {
		
		@Override
		public void handleMessage(final Message message)
		{
			try
			{
				view.logMessage("RECV: CHECK_CONN");
				networkAdapter.send(new ConnectionOkMessage());
			}
			catch (InterruptedException e)
			{
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		
	}
	
	public void drawerPass() {
		try {
			networkAdapter.send(new GiveUpMessage());
			view.logMessage("Poddaje się!");

		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}